#ifndef HTTPUTIL_H
#define HTTPUTIL_H

#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QScopedPointer>
#include <memory>
#include "../nlohmann/json.hpp"

using json = nlohmann::json;

class HttpUtil : public QObject {
    Q_OBJECT

public:
    ~HttpUtil();

    static HttpUtil &instance();

    void get(const QString &url,
             const std::function<void(const json &)> &successCallback = nullptr,
             const std::function<void(const QString &)> &errorCallback = nullptr,
             const QMap<QString, QString> &headers = {});

    void post(const QString &url,
              const json &data,
              const std::function<void(const json &)> &successCallback = nullptr,
              const std::function<void(const QString &)> &errorCallback = nullptr,
              const QMap<QString, QString> &headers = {});

    void put(const QString &url,
             const json &data,
             const std::function<void(const json &)> &successCallback = nullptr,
             const std::function<void(const QString &)> &errorCallback = nullptr,
             const QMap<QString, QString> &headers = {});

    void del(const QString &url,
             const std::function<void(const json &)> &successCallback = nullptr,
             const std::function<void(const QString &)> &errorCallback = nullptr,
             const QMap<QString, QString> &headers = {});

private:
    explicit HttpUtil(QObject *parent = nullptr);

    HttpUtil(const HttpUtil &) = delete;

    HttpUtil &operator=(const HttpUtil &) = delete;

    QNetworkAccessManager *m_manager;
    QString m_baseUrl;
    bool m_initialized = false;

    void httpInit();

    void sendRequest(const QString &url,
                     const QString &method,
                     const json &data = {},
                     const std::function<void(const json &)> &successCallback = nullptr,
                     const std::function<void(const QString &)> &errorCallback = nullptr,
                     const QMap<QString, QString> &headers = {});

    void handleResponse(QNetworkReply *reply,
                        const std::function<void(const json &)> &successCallback,
                        const std::function<void(const QString &)> &errorCallback);
};

#endif // HTTPUTIL_H
